package org.zjx.resource;

import com.fasterxml.jackson.databind.JavaType;
import com.google.gson.reflect.TypeToken;
import lombok.SneakyThrows;
import org.zjx.common.entity.Font;

import java.awt.image.BufferedImage;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class GameRes {
    public static final String RES_FONT = "字体资源";
    public static final String RES_JOB = "任务资源";
    public static final String RES_PROP = "道具资源";
    public static final String RES_ROOM = "房间资源";
    public static final String RES_SCREEN = "场景资源";
    public static final String RES_RACE = "种族资源";
    public static final String RES_SECTS = "门派资源";
    public static final String RES_WAYPOINT = "传送路径资源";
    public static final String RES_WINDOW_SCREEN = "界面窗口类型资源";
    public static final String RES_ERROR = "识别不了的界面信息";

    private static final class InstanceHolder {
        static final GameRes instance = new GameRes();
    }

    public static GameRes getInstance() {
        return GameRes.InstanceHolder.instance;
    }

    public GameRes() {
    }

    /**
     * 调整资源参数（内部方法）
     */
    private ResourceParams adjustResourceParams(String resType, String classify, String fileName) {
        switch (resType) {
            case RES_FONT:
                resType = "fonts";
                break;
            case RES_JOB:
                resType = "jobs";
                break;
            case RES_ERROR:
                resType = "errors";
                break;
            case RES_PROP:
            case RES_ROOM:
            case RES_SCREEN:
            case RES_RACE:
            case RES_SECTS:
            case RES_WAYPOINT:
                fileName = resType;
                break;
        }
        return new ResourceParams(resType, classify, fileName);
    }

    public BufferedImage loadImage(String resType, String classify, String fileName) {
        ResourceParams params = adjustResourceParams(resType, classify, fileName);
        return ResourceManager.getInstance().loadImageResource(params.resType, params.classify, params.fileName);
    }

    /**
     * 加载资源 - 泛型版本
     *
     * @param resType      资源类型
     * @param classify     分类
     * @param fileName     文件名
     * @param resourceType 资源格式（加密/明文）
     * @param type         目标类型
     * @return 解析后的对象
     */
    public <T> T loadGenericResource(String resType, String classify, String fileName,
                                     ResourceManager.ResourceType resourceType, JavaType type) {
        ResourceParams params = adjustResourceParams(resType, classify, fileName);
        return ResourceManager.getInstance().parseResourceToGenericObject(
                params.resType,
                params.classify,
                params.fileName,
                resourceType,
                type
        );
    }

    /**
     * 加载资源 - 类类型版本
     *
     * @param resType      资源类型
     * @param classify     分类
     * @param fileName     文件名
     * @param resourceType 资源格式（加密/明文）
     * @param classType    目标类
     * @return 解析后的对象
     */
    public <T> T loadResource(String resType, String classify, String fileName,
                              ResourceManager.ResourceType resourceType, Class<T> classType) {
        ResourceParams params = adjustResourceParams(resType, classify, fileName);
        return ResourceManager.getInstance().parseResourceToObject(
                params.resType,
                params.classify,
                params.fileName,
                resourceType,
                classType
        );
    }

    /**
     * 加载资源 - 简化版（默认明文）
     *
     * @param resType   资源类型
     * @param classify  分类
     * @param fileName  文件名
     * @param classType 目标类
     * @return 解析后的对象
     */
    public <T> T loadResource(String resType, String classify, String fileName, Class<T> classType) {
        ResourceManager.ResourceType resourceType = ResourceManager.ResourceType.PLAIN_TEXT;
        if (ResourceManager.CONFIG != null && ResourceManager.CONFIG.isEncryptor()) {
            resourceType = ResourceManager.ResourceType.ENCRYPTED;
        }
        return loadResource(resType, classify, fileName, resourceType, classType);
    }

    /**
     * 加载列表资源 - 泛型版本
     *
     * @param resType      资源类型
     * @param classify     分类
     * @param fileName     文件名
     * @param resourceType 资源格式
     * @param elementType  列表元素类型
     * @return 解析后的列表
     */
    public <T> List<T> loadListResource(String resType, String classify, String fileName,
                                        ResourceManager.ResourceType resourceType, Class<T> elementType) {
        ResourceParams params = adjustResourceParams(resType, classify, fileName);
        Type listType = TypeToken.getParameterized(List.class, elementType).getType();
        return ResourceManager.getInstance().parseResourceToGenericObject(
                params.resType,
                params.classify,
                params.fileName,
                resourceType,
                listType
        );
    }

    /**
     * 加载列表资源 - 简化版（默认明文）
     *
     * @param resType     资源类型
     * @param classify    分类
     * @param fileName    文件名
     * @param elementType 列表元素类型
     * @return 解析后的列表
     */
    public <T> List<T> loadListResource(String resType, String classify, String fileName, Class<T> elementType) {
        ResourceManager.ResourceType resourceType = ResourceManager.ResourceType.PLAIN_TEXT;
        if (ResourceManager.CONFIG != null && ResourceManager.CONFIG.isEncryptor()) {
            resourceType = ResourceManager.ResourceType.ENCRYPTED;
        }
        return loadListResource(resType, classify, fileName, resourceType, elementType);
    }


    public void saveImage(BufferedImage image, String resType, String classify, String fileName) {
        new Thread(() -> {
            saveInnerImage(image, resType, classify, fileName);
        }).start();
    }

    @SneakyThrows
    private void saveInnerImage(BufferedImage image, String resType, String classify, String fileName) {
        ResourceParams params = adjustResourceParams(resType, classify, fileName);
        String filePath = ResourceManager.getInstance().getResourcePath(params.resType, params.classify, params.fileName, ResourceManager.ResourceType.PLAIN_IMAGE);
        // 确保目录存在
        Path path = Paths.get(filePath);
        Files.createDirectories(path.getParent());
        ResourceManager.getInstance().saveImageResource(image, params.resType, params.classify, params.fileName);
    }

    /**
     * 保存资源
     *
     * @param resType  资源类型
     * @param classify 分类
     * @param fileName 文件名
     */
    public void saveResource(Object object, String resType, String classify, String fileName) {
        saveInnerResource(object, resType, classify, fileName);
    }

    private void saveInnerResource(Object object, String resType, String classify, String fileName) {
        ResourceParams params = adjustResourceParams(resType, classify, fileName);
        if (ResourceManager.CONFIG != null && ResourceManager.CONFIG.isEncryptor()) {
            ResourceManager.getInstance().saveResource(object, params.resType, params.classify, params.fileName);
        } else {
            ResourceManager.getInstance().saveResourceWithoutEncryption(object, params.resType, params.classify, params.fileName);
        }
    }

    //

    public static void main(String[] args) {
        ResourceManager.CONFIG = new Config_800_600();

//        String fontType = FontAttribute.TASKBAR;
//        List<Waypoint> list = new WaypointDB().findAll();
//        saveResource(list,RES_WAYPOINT,null,fontType);

        // 示例1：加载字体列表
        List<Font> fonts = GameRes.getInstance().loadListResource(
                RES_FONT,
                null,
                FontAttribute.NPC,
                Font.class
        );

        for (Font font : fonts) {
            System.out.println(font);
        }
    }

    /**
     * 资源参数容器类
     */
    private static class ResourceParams {
        final String resType;
        final String classify;
        final String fileName;

        ResourceParams(String resType, String classify, String fileName) {
            this.resType = resType;
            this.classify = classify;
            this.fileName = fileName;
        }
    }
}